package com.gjintel.workflow.trade.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;

import java.util.*;

import com.gjintel.auction.business.model.AuctionCompareBid;
import com.gjintel.auction.business.model.AuctionInfo;
import com.gjintel.auction.business.model.DicStatus;
import com.gjintel.auction.business.service.IAuctionCompareBidService;
import com.gjintel.auction.business.service.IAuctionService;
import com.gjintel.auction.business.service.IDicStatusService;

import com.gjintel.auction.business.service.ISendNotifyService;
import com.gjintel.business.proj.service.impl.ProjectInfoServiceImpl;
import com.gjintel.business.webcontent.model.WebContent;
import com.gjintel.business.webcontent.service.IWebContentService;
import com.gjintel.framework.constant.ActivitiMap;
import com.gjintel.framework.constant.Constant;
import com.gjintel.framework.constant.ProjectStatusAuction;

import com.gjintel.framework.dataset.service.IDataSetService;
import com.gjintel.framework.register.service.IRegisterUserService;
import com.gjintel.framework.res.model.Resources;
import com.gjintel.framework.res.service.IResService;
import com.gjintel.framework.user.model.User;
import com.gjintel.framework.user.service.IUserService;
import com.gjintel.framework.util.CommUtil;

import com.gjintel.framework.util.FileResUtil;
import com.gjintel.sdk.util.DateUtils;
import com.gjintel.sdk.util.StringUtil;
import com.gjintel.sdk.util.WordHandler;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;

import org.activiti.engine.runtime.Execution;

import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import com.gjintel.framework.common.service.IDepositExecuteService;

import com.gjintel.framework.dataset.service.impl.DataSetServiceImpl;
import com.gjintel.framework.holidayset.service.IHolidaySetService;
import com.gjintel.framework.log.model.TSysWarningLog;
import com.gjintel.framework.log.service.impl.MessageServiceImpl;

import com.gjintel.framework.role.service.IRoleService;

import com.gjintel.workflow.trade.service.IExecutionService;


@Service("executionService")
@SuppressWarnings({"rawtypes", "unchecked"})
public class ExecutionServiceImpl implements IExecutionService {

    @Autowired
    private IAuctionService auctionService;

    @Autowired
    private WorkflowProcessInstanceServiceImpl workflowProcessInstanceService;


    @Autowired
    private TaskService taskService;

    @Autowired
    private DataSetServiceImpl dataSetService;


    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private IHolidaySetService holidaySetServiceImpl;

    @Autowired
    private MessageServiceImpl messageService;

    @Autowired
    private IRoleService roleService;

    @Autowired
    private IDepositExecuteService depositExecuteService;

    @Autowired
    private IDicStatusService dicStatusService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IRegisterUserService registerUserService;

    @Autowired
    private IAuctionCompareBidService auctionCompareBidService;

    @Autowired
    private ProjectInfoServiceImpl projectInfoService;

    @Autowired
    private IHolidaySetService holidaySetService;

    @Autowired
    private ISendNotifyService sendNotifyService;

    @Autowired
    private IWebContentService webContentService;

    @Override
    public void genMsg(Execution execution, String statusCode) {

    }

    // @Autowired
    // private IResService resService;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
    private SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm");


    public List<String> UserQuery(String taskId) {
        List<String> list = new ArrayList<String>();
        String groupId = null;
        String userId = null;
        List<IdentityLink> list1 = taskService.getIdentityLinksForTask(taskId);
        for (IdentityLink identityLink : list1) {
            userId = identityLink.getUserId();
            groupId = identityLink.getGroupId();
            if (userId != null) {
                list.add(userId);
            }
            if (groupId != null) {
                List<org.activiti.engine.identity.User> users = identityService.createUserQuery().memberOfGroup(groupId).list();
                for (org.activiti.engine.identity.User user : users) {
                    list.add(user.getId());
                }
            }
        }
        return list;
    }


    @Override
    public void alterStatusAndGenMsg(Execution execution, String statusCode) {
        //TODO 1.根据 statusCode,查找  t_dic_workflow_status.code 转换成 status
        //根据流程idl转换竞拍表的status
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        int newValue = ProjectStatusAuction.valueOf(statusCode).toValue();
        System.out.println("statusCode: " + statusCode);
        auctionInfo.setStatus(newValue);
        auctionService.saveOrUpdate(auctionInfo);

        //发送通知
        switch (statusCode) {
            case "REJECT":
                //发送项目审核不通过通知给产权人
                sendNotifyService.sendProjectAuditNoNotify(auctionInfo);
                break;
            case "TERMINAL":
                //发送项目终止通知给产权人
                sendNotifyService.sendProjectTerminateNotify(auctionInfo);
                break;
            case "EVALUATE":
                //发送项目暂停审核通知业务管理员组和给产权人通知
                sendNotifyService.sendProjectPauseAuditNotify(auctionInfo);
                break;
            case "SHOW_PAUSE":
                //发送项目暂停审核通过通知给产权人
                sendNotifyService.sendProjectPauseYesNotify(auctionInfo);
                break;
            case "AUCTIONING":
                //发送竞拍开始通知给产权人
                sendNotifyService.sendAuctionStartNotify(auctionInfo);
                break;
            case "CENTER_CONFIRM":
                //发送竞价确认结果通知给审核人审核
                sendNotifyService.sendAuctionConfirmReslutNotify(auctionInfo);
                break;
            case "FLOW_SHOW":
                //发送流标通知 给产权人和审核人
                sendNotifyService.SendFlowNotify(auctionInfo);
                break;
            case "HIT_SHOW":
                //发送中标通知 给产权人,中标人和审核人
                sendNotifyService.SendWinningNotify(auctionInfo);
                break;
            case "EVALUATE_HIT":
                //发送中标公示暂停审核通知业务管理员组和给产权人通知
                sendNotifyService.sendWinningPublicPauseAuditNotify(auctionInfo);
                break;
            case "RESULT_SHOW":
                //发送中标公示暂停审核不通过通知给产权人
                sendNotifyService.sendWinningPublicPauseNoNotify(auctionInfo);
                break;
            case "PAUSE_HIT":
                //发送中标公示暂停审核通过通知给产权人
                sendNotifyService.sendWinningPublicYesNotify(auctionInfo);
                break;
            case "SHOW_CONTRACT_OVER":
                //提醒产权人和审核人发放中标通知书
                sendNotifyService.remindWinningNotifyGrant(auctionInfo);
                break;
            case "PUBLISH_OVER":
            case "UP_CONTACT"://解锁合同
                //给产权人 中标人 发送上传合同通知
                sendNotifyService.sendUploadContractNotify(auctionInfo);
                break;
            case "LOCK_CONTRACT":
                //发送合同审核通知给 审核人
                sendNotifyService.sendContractLockNotify(auctionInfo);
                break;
            case "AUDIT_CONTRACT":
                //发送上传合同锁定通知给产权人和中标人
                sendNotifyService.sendContractAuditNotify(auctionInfo);
                break;
            case "CONTRACT_AUDIT_NOPASS":
                //发送合同审核不通过通知给 产权人和中标人
                sendNotifyService.sendContractAuditNoNotify(auctionInfo);
                break;
            case "SHOW_CONTRACT":
                //发送合同审核通过通知给 产权人和中标人
                sendNotifyService.sendContractAuditYesNotify(auctionInfo);
                break;
            case "END":
                auctionInfo.setEndTime(new Date());
                auctionService.saveOrUpdate(auctionInfo);
                break;
        }
    }

    @Override
    public void genDocument(Execution execution) {
        System.out.print("我是分隔号-------------------------------------------\n");
        System.out.println("发布中标 通知书流程已经触发 ，流程号id is:" + execution.getProcessInstanceId() + "\n");
    }

    //超时
    @Override
    public void setFlowVar(Execution execution) {
        String processId = execution.getProcessInstanceId();

//        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
//        int flowPublicity = dataSetService.getDataSet().getFlowPublicity();//流标公示时间
//        Date date = new Date();
//        Date flowEndTime = DateUtils.computeWorkDayDate(holidaySetService, date, flowPublicity);//产权人中标结果超时时间
//        auctionInfo.setFlowshowStart(date);//流标公示开始时间
//        auctionInfo.setFlowshowEnd(flowEndTime);//流标公示结束时间
//        //公告ID
//        String documentId = (String) runtimeService.getVariable(processId, "documentId");
//        WebContent webContent = webContentService.get(WebContent.class, documentId);
//        //更新流标公告
//        genFlowWebContent(webContent, auctionInfo);
//        webContent.setCreateTime(date);
//        webContent.setEndShowTime(flowEndTime);// 设置展示结束时间
//        webContent.setIsDisplay(1);//1 = 不显示
//        webContentService.saveOrUpdate(webContent);
//        auctionService.saveOrUpdate(auctionInfo);

        runtimeService.setVariable(processId, "isFlow", Constant.OWNER_CHOOSE_AUCTION_RESLUT_TYPE_OUT_TIME_FLOW);//因产权单位未在规定时间内确认结果而造成流标
        runtimeService.setVariable(processId, "flowDown", true);   //设置流标为true,在下一个关口使用并判断
    }

    //发送竞价结果通知给产权人
    @Override
    public void sendAuctionReslutNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendAuctionReslutNotify(auctionInfo);
        System.out.println("发送竞价结果通知给产权人");
    }

    //发送竞价结果审核不通过结果给产权人
    @Override
    public void sendNoAuctionConfirmReslutNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendNoAuctionConfirmReslutNotify(auctionInfo);
        System.out.println("发送竞价结果审核不通过结果给产权人");
    }

    //发送超时编辑项目通知给产权人
    @Override
    public void sendEditProjectNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendEditProjectNotify(auctionInfo);
        System.out.println("发送超时编辑项目通知给产权人");
    }

    //发送项目审核通知给审核人
    @Override
    public void sendProjectAuditorNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendProjectAuditorNotify(auctionInfo);
        System.out.println("发送项目审核通知给审核人");
    }

    //发送项目审核通知给所有审核人
    @Override
    public void sendAllAuditorGrpNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendAllAuditorGrpNotify(auctionInfo);
        System.out.println("发送项目审核通知给所有审核人");
    }

    //发送竞拍公告通知给产权人
    @Override
    public void sendAuctionPlacardNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendAuctionPlacardNotify(auctionInfo);
        System.out.println("发送竞拍公告通知给产权人");
    }

    //发送项目暂停审核不通过通知给产权人
    @Override
    public void sendProjectPauseNoNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendProjectPauseNoNotify(auctionInfo);
        System.out.println("发送项目暂停审核不通过通知给产权人");
    }

    //发送项目质疑处理完毕继续竞拍通知给产权人
    @Override
    public void sendProjectContinueAuctionNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendProjectContinueAuctionNotify(auctionInfo);
        System.out.println("发送项目质疑处理完毕继续竞拍通知给产权人");
    }

    //发送竞价结果审核通过结果给产权人
    @Override
    public void sendYesAuctionConfirmReslutNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendYesAuctionConfirmReslutNotify(auctionInfo);
        System.out.println("发送竞价结果审核通过结果给产权人");
    }

    //发送中标公示质疑处理完毕继续公示通知给产权人
    @Override
    public void sendWinningContinuePublicNotify(Execution execution) {
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        sendNotifyService.sendWinningContinuePublicNotify(auctionInfo);
        System.out.println("发送中标公示质疑处理完毕继续公示通知给产权人");
    }

    //生成预发公告
    @Override
    public void genPreContent(Execution execution) throws Exception {
        //根据流程idl转换竞拍表的status
        String processId = execution.getProcessInstanceId();
        AuctionInfo auctionInfo = auctionService.findByProcessId(processId);
        if (auctionInfo == null) {
            throw new Exception("获取竞价信息失败 processId:" + processId);
        }
        AuctionCompareBid auctionCompareBid = auctionCompareBidService.findTopOneByAuctionId(auctionInfo.getId());
        int auditTimeout = dataSetService.getDataSet().getAuditTimeout();
        Date date = new Date();
        String updateEndTime = DateUtils.computeWorkDayDateStr(holidaySetService, date, auditTimeout);//产权人中标结果超时时间
        runtimeService.setVariable(execution.getId(), "updateEndTime", StringUtil.getISODate(updateEndTime));//公告变量
//        String auctionPublicityDocumentId = (String) runtimeService.getVariable(execution.getId(), "auctionPublicityDocumentId");//竞价公告变量
//        if (auctionPublicityDocumentId != null && auctionPublicityDocumentId.length() > 0) {
//            WebContent webContent = webContentService.get(WebContent.class, auctionPublicityDocumentId);
//            //webContent.setIsOpen(PUBLICITY_IN);
//            webContentService.saveOrUpdate(webContent);
//        }
        if (auctionCompareBid == null) {
            int flowPublicity = dataSetService.getDataSet().getFlowPublicity();//流标公示时间
            Date flowEndTime = DateUtils.computeWorkDayDate(holidaySetService, date, flowPublicity);//产权人中标结果超时时间
            auctionInfo.setFlowshowStart(date);
            auctionInfo.setFlowshowEnd(flowEndTime);

            //没有出价记录
            //发送流标公告
            String webContentId = genFlowWebContent(null, auctionInfo);
            runtimeService.setVariable(execution.getId(), "documentId", webContentId);//公告变量
            runtimeService.setVariable(execution.getId(), "isFlow", Constant.OWNER_CHOOSE_AUCTION_RESLUT_TYPE_AUTO_FLOW);//没有竞拍人自动流标
            //将中标人清空
            auctionInfo.setWinnerId("");
            auctionInfo.setWinnerName("");
            auctionInfo.setHitPrice(.0);
            auctionService.saveOrUpdate(auctionInfo);
            return;
        }
        Long time = System.currentTimeMillis();
        if (time < auctionInfo.getAuctionStart().getTime()) {
            throw new Exception("竞拍还未开始,无法获取,中标人信息 processId:" + processId);
        }
        if (time < auctionInfo.getAuctionEnd().getTime()) {
            throw new Exception("竞拍还未结束,无法获取,中标人信息 processId:" + processId);
        }
        int publicity = dataSetService.getDataSet().getPublicity();//流标公示时间
        Date endTime = DateUtils.computeWorkDayDate(holidaySetService, date, publicity);//中标公示时间
        auctionInfo.setHitShowStart(date);
        auctionInfo.setHitShowEnd(endTime);

        //设置中标人
        auctionInfo.setWinnerId(auctionCompareBid.getBiddrId());
        auctionInfo.setWinnerName(auctionCompareBid.getBidderName());
        auctionInfo.SetHitPriceBig(auctionCompareBid.getBidderPrice());
        String webContentId = genHitWebContent(auctionInfo);//生成中标公告webcontent
        runtimeService.setVariable(execution.getId(), "documentId", webContentId);
        runtimeService.setVariable(execution.getId(), "isFlow", Constant.OWNER_CHOOSE_AUCTION_RESLUT_TYPE_SUCCESS);//是否流标
        auctionService.saveOrUpdate(auctionInfo);
    }

    /**
     * 发布流标公告
     */
    @Override
    public String genFlowWebContent(WebContent web, AuctionInfo auctionInfo) {
        if (web == null) {
            web = new WebContent();
        }
        WordHandler world = new WordHandler();
        Map map = new HashMap();
        map.put("auctionInfo", auctionInfo);

        map.put("flowTime", sdf.format(auctionInfo.getFlowshowStart()));
        world.generateWord("flowNotice.html", map, "flowNotice.html");// worldXmlPath
        String content = "";
        File file = new File("flowNotice.html");
        try {
            content = FileUtils.readFileToString(file, "utf-8");
            file.delete();// 删除生成的文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        String title = "【" + auctionInfo.getCatagoryName() + "】 " + auctionInfo.getAuctionName() + "（" + auctionInfo.getCode() + "）流标公告";
        web.setTitle(title);
        web.setContent(content);
        web.setCreaterId(ActivitiMap.SUPERADMIN_ID);
        web.setCreateTime(auctionInfo.getFlowshowStart());
        web.setCreaterName("系统");
        web.setDeptId("1");
        web.setProjectId(auctionInfo.getId());
        web.setType("33");
        web.setIsDisplay(1);//不显示
        web.setEndShowTime(auctionInfo.getFlowshowEnd());// 设置展示结束时间
        projectInfoService.saveOrUpdate(web);
        return web.getId();
    }

    /**
     * 生成中标公告webcontent
     */
    private String genHitWebContent(AuctionInfo auctionInfo) throws Exception {
       // User userInfo = userService.get(User.class, auctionInfo.getOwnerId());
//        if (userInfo == null) {
//            throw new Exception("获取产权人信息失败 auctionInfo.getOwnerId():" + auctionInfo.getOwnerId());
//        }
        // 1.使用cms系统发布公告，2.发送提醒信息
        WordHandler world = new WordHandler();
        WebContent web = new WebContent();
        Map map = new HashMap();
        map.put("auctionInfo", auctionInfo);
      //  map.put("userInfo", userInfo);
        map.put("createTime", sdf.format(auctionInfo.getCreateTime()));//项目创建时间
        int publicity = dataSetService.getDataSet().getPublicity();//公示期

        map.put("hitShowStart", sdf.format(auctionInfo.getHitShowStart()));// 中标公示期开始时间
        map.put("hitShowEnd", sdf.format(auctionInfo.getHitShowEnd().getTime() - 1000));// 中标公示期结束时间
        map.put("hitTime", sdf.format(auctionInfo.getHitShowStart()));// 发布时间

        //评审纪要
        String attachment = "";
        map.put("attachment", attachment);// 附件 评审纪要

        world.generateWord("hitNotice.html", map, "hitNotice.html");// 生成内容worldXmlPath
        File file = new File("hitNotice.html");
        String content = "";
        try {
            content = FileUtils.readFileToString(file, "utf-8");
            file.delete();// 删除生成的文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        String title = "【" + auctionInfo.getCatagoryName() + "】 " + auctionInfo.getAuctionName() + "（" + auctionInfo.getCode() + "）中标公告";
        web.setTitle(title);
        web.setContent(content);
        web.setCreaterId(ActivitiMap.SUPERADMIN_ID);
        web.setCreateTime(auctionInfo.getHitShowStart());
        web.setCreaterName("系统");
        web.setDeptId("1");
        web.setProjectId(auctionInfo.getId());
        web.setType("32");
        web.setEndShowTime(auctionInfo.getHitShowEnd());// 设置展示结束时间
        web.setIsDisplay(1);//默认不显示
        projectInfoService.saveOrUpdate(web);
        return web.getId();
    }

    @Override
    public void updateAuctionEndTime(Execution execution) {
        Integer auction_sleep = dataSetService.getDataSet().getAuctionSleep() + 60;
        //增加1分钟,以防万一
        runtimeService.setVariable(execution.getId(), "auction_end_time", "PT" + auction_sleep + "S");
    }
}
